package com.epam.android.mailcomponent.controls;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;

import com.epam.android.mailcomponent.R;
import com.epam.android.mailcomponent.controls.util.MailContent;

public class MailView extends RelativeLayout implements
		View.OnCreateContextMenuListener {

	public static final int REQUEST_CODE_CONTACTS = 0;
	private static final int SHORT_EMAIL_LENGTH = 5;
	private static final String SHORTEN_EMAIL_POSTFIX = "...";
	private static final int MAX_EMAILS_IN_ROW = 3;
	private static final int EMAIL_MARGIN_LEFT = 10;
	private static final int EMAIL_MARGIN_RIGHT = 10;
	private static final int EMAIL_MARGIN_TOP = 2;
	private static final int EMAIL_MARGIN_BOTTOM = 2;

	// Additional layout for views defined in xml
	private LinearLayout additionalLayout;
	private TableLayout emailsToLayout;
	private TableRow emailsToCurRow;
	private TableLayout emailsCcLayout;
	private TableRow emailsCcCurRow;
	private Map<TextView, String> emailsToMap;
	private Map<TextView, String> emailsCcMap;
	private EditText subjectEditText;
	private EditText contentEditText;
	private Button buttonSend;
	private Button buttonCancel;
	private boolean enteringTo;
	private AlertDialog enterEmailMethodDialog;
	private AlertDialog enterEmailManuallyDialog;
	private EditText editTextEmail;
	private View currentView;
	private int displayWidth;

	public MailView(Context context) {
		super(context);
	}

	public MailView(Context context, AttributeSet attrs) {
		super(context, attrs);
		LayoutInflater inflater = (LayoutInflater) context
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		inflater.inflate(R.layout.mail_view, this);
		initDialogs(context);
		initDefaultViews(context);
	}

	public void setSendButtonListener(View.OnClickListener listener) {
		buttonSend.setOnClickListener(listener);
	}

	public void setCancelButtonListener(View.OnClickListener listener) {
		buttonCancel.setOnClickListener(listener);
	}

	public void setContactsPickerListener(
			DialogInterface.OnClickListener listener) {
		enterEmailMethodDialog.setButton(
				getContext().getString(
						R.string.enter_email_method_dialog_contacts_button),
				listener);
	}

	public void displayEmails(List<String> emails) {
		for (String email : emails) {
			addEnteredEmail(email);
		}
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		MenuInflater inflater = new MenuInflater(getContext());
		inflater.inflate(R.menu.email_menu, menu);
		currentView = v;
		MenuItem menuItemEdit = menu.findItem(R.id.menu_edit);
		menuItemEdit
				.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
					@Override
					public boolean onMenuItemClick(MenuItem item) {
						if (enteringTo) {
							editTextEmail.setText(emailsToMap.get(currentView));
						} else {
							editTextEmail.setText(emailsCcMap.get(currentView));
						}
						enterEmailManuallyDialog.show();
						return true;
					}
				});
		MenuItem menuItemDelete = menu.findItem(R.id.menu_delete);
		menuItemDelete
				.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
					@Override
					public boolean onMenuItemClick(MenuItem item) {
						LinearLayout parent = (LinearLayout) currentView
								.getParent();
						parent.removeView(currentView);
						if (enteringTo) {
							emailsToMap.remove(currentView);
						} else {
							emailsCcMap.remove(currentView);
						}
						return true;
					}
				});
	}

	public MailContent getMailContent() {
		MailContent mailContent = new MailContent();
		mailContent.setToEmailsList(getEmailsList(emailsToMap));
		mailContent.setToEmailsList(getEmailsList(emailsCcMap));
		mailContent.setSubject(subjectEditText.getText().toString());
		mailContent.setContent(contentEditText.getText().toString());
		mailContent.setAdditionalLayout(additionalLayout);
		return mailContent;
	}

	@Override
	protected void onFinishInflate() {
		int childCount = getChildCount();
		int layoutId = findViewById(R.id.main_layout).getId();
		for (int i = 0; i < childCount; i++) {
			View child = getChildAt(i);
			int childId = child.getId();
			// if child was defined in xml
			if (childId == View.NO_ID || childId != layoutId) {
				ViewGroup parent = (ViewGroup) child.getParent();
				parent.removeView(child);
				additionalLayout.addView(child);
				i--;
				childCount--;
			}
		}
		super.onFinishInflate();
	}

	private List<String> getEmailsList(Map<TextView, String> map) {
		Set<Entry<TextView, String>> entrySet = map.entrySet();
		List<String> mails = new ArrayList<String>();
		for (Entry<TextView, String> entry : entrySet) {
			mails.add(entry.getValue());
		}
		return mails;
	}

	private void initDialogs(Context context) {
		// Dialog for entering email method
		AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
		dialogBuilder.setMessage(R.string.enter_email_method_dialog_message);
		enterEmailMethodDialog = dialogBuilder.create();
		enterEmailMethodDialog.setButton(context
				.getString(R.string.enter_email_method_dialog_contacts_button),
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						Toast.makeText(getContext(),
								R.string.no_get_contacts_listener_toast,
								Toast.LENGTH_SHORT).show();
					}
				});
		enterEmailMethodDialog.setButton3(context
				.getString(R.string.enter_email_method_dialog_manually_button),
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						getEmailsManually();
					}
				});
		enterEmailMethodDialog.setButton2(context
				.getString(R.string.enter_email_method_dialog_cancel_button),
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						enterEmailMethodDialog.dismiss();
					}
				});

		// Dialog for entering email manually
		dialogBuilder = new AlertDialog.Builder(context);
		LayoutInflater factory = LayoutInflater.from(context);
		View dialogLayout = factory.inflate(R.layout.enter_email_dialog, null);
		dialogBuilder.setView(dialogLayout);
		enterEmailManuallyDialog = dialogBuilder.create();
		Button buttonEnter = (Button) dialogLayout
				.findViewById(R.id.button_enter);
		buttonEnter.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				if (currentView == null) {
					addEnteredEmail(editTextEmail.getText().toString());
				} else {
					String longEmail = editTextEmail.getText().toString();
					String shortEmail = shortenEmail(longEmail);
					((TextView) currentView).setText(shortEmail);
					if (enteringTo) {
						emailsToMap.put((TextView) currentView, longEmail);
					} else {
						emailsCcMap.put((TextView) currentView, longEmail);
					}
					currentView = null;
					editTextEmail.setText(new String());
				}
				enterEmailManuallyDialog.dismiss();
			}
		});
		Button buttonCancel = (Button) dialogLayout
				.findViewById(R.id.button_cancel);
		buttonCancel.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				editTextEmail.setText(new String());
				enterEmailManuallyDialog.dismiss();
			}
		});
		this.editTextEmail = (EditText) dialogLayout
				.findViewById(R.id.email_edit_text);
	}

	private void initDefaultViews(Context context) {
		buttonSend = (Button) findViewById(R.id.send_button);
		buttonCancel = (Button) findViewById(R.id.cancel_button);
		Button buttonTo = (Button) findViewById(R.id.to_button);
		buttonTo.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				enteringTo = true;
				currentView = null;
				enterEmailMethodDialog.show();
			}
		});
		Button buttonCc = (Button) findViewById(R.id.cc_button);
		buttonCc.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				enteringTo = false;
				currentView = null;
				enterEmailMethodDialog.show();
			}
		});
		additionalLayout = (LinearLayout) findViewById(R.id.additional_layout);
		emailsToLayout = (TableLayout) findViewById(R.id.to_emails_layout);
		emailsCcLayout = (TableLayout) findViewById(R.id.cc_emails_layout);
		subjectEditText = (EditText) findViewById(R.id.subject_edit_text);
		contentEditText = (EditText) findViewById(R.id.content_edit_text);
		emailsToMap = new HashMap<TextView, String>();
		emailsCcMap = new HashMap<TextView, String>();

		WindowManager windowManager = (WindowManager) getContext()
				.getSystemService(Context.WINDOW_SERVICE);
		displayWidth = windowManager.getDefaultDisplay().getWidth();
	}

	private void getEmailsManually() {
		enterEmailManuallyDialog.show();
	}

	private void addEnteredEmail(String emailAddress) {
		TextView email = new TextView(getContext());
		email.setText(emailAddress);
		email.setBackgroundResource(R.drawable.mail_element);
		email.setTextColor(Color.BLACK);
		email.setOnCreateContextMenuListener(this);
		if (enteringTo) {
			// add email to "To"
			addEmail(emailAddress, email, emailsToLayout, emailsToCurRow,
					emailsToMap);
		} else {
			// add email to "Cc"
			addEmail(emailAddress, email, emailsCcLayout, emailsCcCurRow,
					emailsCcMap);
		}
		editTextEmail.setText(null);
	}

	private void addEmail(String emailAddress, TextView email,
			TableLayout layout, TableRow row, Map<TextView, String> map) {
		// check such email existence
		if (!map.containsValue(emailAddress)) {
			email.setText(shortenEmail(emailAddress));
			if (row == null || row.getChildCount() % MAX_EMAILS_IN_ROW == 0) {
				row = new TableRow(getContext());
				TableLayout.LayoutParams rowParams = new TableLayout.LayoutParams(
						TableLayout.LayoutParams.FILL_PARENT,
						TableLayout.LayoutParams.WRAP_CONTENT);
				row.setLayoutParams(rowParams);
				if (enteringTo) {
					emailsToCurRow = row;
				} else {
					emailsCcCurRow = row;
				}
				layout.addView(row);
			}
			TableRow.LayoutParams emailParams = new TableRow.LayoutParams();
			emailParams.setMargins(EMAIL_MARGIN_LEFT, EMAIL_MARGIN_TOP,
					EMAIL_MARGIN_RIGHT, EMAIL_MARGIN_BOTTOM);
			email.setLayoutParams(emailParams);
			row.addView(email);
			map.put(email, emailAddress);
		}
	}

	private String shortenEmail(String email) {
		if (email.length() > SHORT_EMAIL_LENGTH) {
			return email.substring(0, SHORT_EMAIL_LENGTH)
					+ SHORTEN_EMAIL_POSTFIX;
		} else {
			return email;
		}
	}

}